//
//  ChatController.swift
//  聊天界面
//
//  Created by smile on 2019/4/22.
//  Copyright © 2019 ixuea. All rights reserved.
//

import UIKit

//TextView实现提示文字框架
import KMPlaceholderTextView

//发布订阅框架
import SwiftEventBus

//图片选择
import PhotoSolution

class ChatController: BaseTitleController {
    
    /// 列表
    @IBOutlet weak var tableView: UITableView!
    
    /// 输入框容器
    @IBOutlet weak var vwInputContainer: UIView!
    
    /// 输入框容器边框
    @IBOutlet weak var vwInputBorder: UIView!
    
    /// 输入框
    @IBOutlet weak var tvContent: KMPlaceholderTextView!
    
    var userId:String!
    
    var dataArray:[JMSGMessage] = []
    
    /// 原来的消息Id
    /// 用来获取历史消息
    var oldMessageId:Int = -1
    
    var conversation:JMSGConversation!
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        // Do any additional setup after loading the view.
    }
    
    override func initViews() {
        super.initViews()
        
        setTitle("聊天")
        
        ViewUtil.showSmallRadius(view: vwInputBorder)
        
        //设置输入框圆角
        ViewUtil.showSmallRadius(view: vwInputBorder)
        
        //设置输入框边框
        vwInputBorder.showColorPrimaryBorder()
        
        //注册Cell
        
        tableView.register(UINib(nibName: ChatTextLeftCell.NAME, bundle:nil), forCellReuseIdentifier: ChatTextLeftCell.NAME)
        
        
        tableView.register(UINib(nibName: ChatTextRightCell.NAME, bundle:nil), forCellReuseIdentifier: ChatTextRightCell.NAME)
        
        tableView.register(UINib(nibName: ChatImageLeftCell.NAME, bundle:nil), forCellReuseIdentifier: ChatImageLeftCell.NAME)
        
        tableView.register(UINib(nibName: ChatImageRightCell.NAME, bundle:nil), forCellReuseIdentifier: ChatImageRightCell.NAME)
        
        //添加一条自动布局约束
        //含义是：输入框的底部锚点
        //等于当前界面中View的底部锚点
        //也就说这个框架
        vwInputContainer.bottomAnchor.constraint(equalTo: view.keyboardLayoutGuide.topAnchor).isActive = true
    }
    
    override func initDatas() {
        super.initDatas()
        
        //获取对方用户信息
        UserManager
            .shared()
            .getUser(StringUtil.removeUserId(userId)) { (data) in
                
                //设置标题
                self.setTitle(data.nickname!)
            }
        
        
        //创建会话
        //如果本地已经存在
        //不会重复创建
        //而是直接返回已经存在的会话
        JMSGConversation.createSingleConversation(withUsername:userId) { (conversation, error) in
            self.conversation=conversation as? JMSGConversation
            
            //清除未读
            self.conversation.clearUnreadCount()
            
            //发送未读消息数量变更通知
            SwiftEventBus.post(ON_MESSAGE_COUNT_CHANGED)
        }
    }
    
    func fetchData() {
        dataArray.removeAll()
        loadMore()
    }
    
    func loadMore() {
        //查询历史消息
        self.conversation.allMessages({ (messages, error) in
            if let messages = messages as? [JMSGMessage] {
                
                //这里对聊天的消息按照日期升序
                //也就是最小的日志在前面
                self.dataArray = self.dataArray + DataUtil.processMessage(messages)
                self.tableView.reloadData()
                
                self.scrollToBottom()
            }
        })
        
    }
    
    override func initListeners() {
        super.initListeners()
        
        //设置代理
        tvContent.delegate=self
    }
    
    /// 选择图片按钮点击回调方法
    ///
    /// - Parameter sender: <#sender description#>
    @IBAction func onSelectImageClick(_ sender: Any) {
        print("ChatController onSelectImageClick")
        
        //初始化选择图片框架
        let photoSolution = PhotoSolution()
        photoSolution.delegate = self
        
        //返回的图片要压缩
        //不然太大了
        photoSolution.customization.returnImageSize = .compressed
        
        //选择最大1张图片
        let PhotoPickerController=photoSolution.getPhotoPicker(maxPhotos: 1)
        
        //显示控制栏
        present(PhotoPickerController, animated: true, completion: nil)
        
    }
    
    /// 视图已经可见了
    ///
    /// - Parameter animated: <#animated description#>
    override func viewDidAppear(_ animated: Bool) {
        super.viewDidAppear(animated)
        
        //重新获取数据
        fetchData()
        
        //监听消息
        JMessage.add(self, with: conversation)
        
        //将用来Id设置到代理中
        AppDelegate.shared.currentChatUserId=userId
       
    }
    
    /// 视图即将消失
    ///
    /// - Parameter animated: animated description
    override func viewDidDisappear(_ animated: Bool) {
        super.viewDidDisappear(animated)
        //界面不可见
        //移除监听
        //可以提高效率
        JMessage.remove(self, with: conversation)
        
        //清除Id
        AppDelegate.shared.currentChatUserId=nil
    }

    /*
     // MARK: - Navigation
     
     // In a storyboard-based application, you will often want to do a little preparation before navigation
     override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
     // Get the new view controller using segue.destination.
     // Pass the selected object to the new view controller.
     }
     */
    
}

// MARK: - 启动界面
extension ChatController{
    /// 启动界面
    ///
    static func start(_ navigationController:UINavigationController,_ userId:String) {
        //创建控制器
        let controller=navigationController.storyboard?.instantiateViewController(withIdentifier: "Chat") as! ChatController
        
        controller.userId=userId
        
        //将控制器压入导航控制中
        navigationController.pushViewController(controller, animated: true)
        
    }
}

// MARK: - 列表数据源和代理
extension ChatController: UITableViewDataSource,UITableViewDelegate {
    
    // MARK:- TableView数据源
    /// 返回有多个条目
    /// 和CollectionView差不多
    ///
    /// - Parameters:
    ///   - tableView: <#tableView description#>
    ///   - section: <#section description#>
    /// - Returns: <#return value description#>
    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return dataArray.count
    }
    
    /// 返回当前位置的Cell
    ///
    /// - Parameters:
    ///   - tableView: <#tableView description#>
    ///   - indexPath: <#indexPath description#>
    /// - Returns: <#return value description#>
    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let data = dataArray[indexPath.row]
        
        let type=typeForItemAtData(data)
        
        var cell:BaseChatCell!
        
        //根据Cell类型创建Cell
        switch type {
        case .TextLeft:
            cell=tableView.dequeueReusableCell(withIdentifier: ChatTextLeftCell.NAME, for: indexPath) as! BaseChatCell
        case .ImageLeft:
            cell=tableView.dequeueReusableCell(withIdentifier: ChatImageLeftCell.NAME, for: indexPath) as! BaseChatCell
        case .ImageRight:
            cell=tableView.dequeueReusableCell(withIdentifier: ChatImageRightCell.NAME, for: indexPath) as! BaseChatCell
        default:
            cell=tableView.dequeueReusableCell(withIdentifier: ChatTextRightCell.NAME, for: indexPath) as! BaseChatCell
        }
        
        //绑定数据
        cell.bindData(data)
        
        return cell
    }
    
    /// 即将显示Cell
    ///
    /// - Parameters:
    ///   - tableView: <#tableView description#>
    ///   - cell: <#cell description#>
    ///   - indexPath: <#indexPath description#>
    func tableView(_ tableView: UITableView, willDisplay cell: UITableViewCell, forRowAt indexPath: IndexPath) {
        //取出数据
        guard let cell = cell as? BaseChatCell else {
            return
        }
        
        let data=dataArray[indexPath.row]
        
        cell.bindData(data)
    }
    
    /// 获取列表类型
    ///
    /// - Parameter data: <#data description#>
    /// - Returns: <#return value description#>
    func typeForItemAtData(_ data:JMSGMessage) -> CellType {
        //消息方向
        let isReceived = data.isReceived
        
        //判断消息类型
        if JMSGContentType.image == data.contentType {
            //图片消息
            
            //在判断是谁发的
            //接收的消息显示在左侧（对方发的）
            //我发送的消息在右边
            return isReceived ? CellType.ImageLeft : CellType.ImageRight
        }
        
        //TODO 其他消息可以继续在这里扩展
        
        //文本消息
        return isReceived ? .TextLeft : .TextRight
    }
    
    /// Cell类型；这是一个枚举
    enum CellType {
        //左边，文本消息，其他人发的
        case TextLeft
        
        //右边，文本消息，我发的
        case TextRight
        
        //左边，图片消息，其他人发的
        case ImageLeft
        
        //右边，图片消息，我发的
        case ImageRight
    }
}


// MARK: - TextView代理
extension ChatController:UITextViewDelegate{
    
    /// 监听文本输入
    ///
    /// - Parameters:
    ///   - textView: <#textView description#>
    ///   - range: <#range description#>
    ///   - text: <#text description#>
    /// - Returns: <#return value description#>
    func textView(_ textView: UITextView, shouldChangeTextIn range: NSRange, replacementText text: String) -> Bool {
        print("ChatController controller shouldChangeTextInRange:\(text)")
        
        //判断输入的字是否是回车，即按下return
        if text=="\n" {
            //return按钮
            print("return click:\(text)")
            
            self.sendTextMessage()
            
            return false
        }
        
        //其他情况返回true
        //表示其他字符正常输入
        return true
    }
}

// MARK: - 发送消息
extension ChatController{
    
    /// 发送文本信息
    func sendTextMessage() {
        /// 发送文本信息
        //获取输入的内容
        let content=tvContent.text?.trim()
        
        if content!.isEmpty {
            ToastUtil.short("请输入内容！")
            return
        }
        
        conversation.sendTextMessage(content!)
    }
    
    /// 清除输入框
    func clearTextView() {
        tvContent.text=""
    }
    
    /// 将消息条到界面
    ///
    /// - Parameter message: <#message description#>
    func addMessage(_ message: JMSGMessage!) {
        //将消息添加到列表最后
        dataArray.append(message)
        
        //刷新列表
        tableView.reloadData()
        
        scrollToBottom()
    }
    
    /// 让聊天界面滚动到底部
    func scrollToBottom() {
        DispatchQueue.main.async {
            if self.dataArray.count>0 {
                //有数据就滚动到底部
                let indexPath=IndexPath(item: self.dataArray.count-1, section: 0)
                self.tableView.scrollToRow(at: indexPath, at: .bottom, animated: false)
            }
        }
        
        
    }
    
    /// 发送图片消息
    ///
    /// - Parameter data: <#data description#>
    func sendImageMessage(_ data:UIImage)  {
        //获取输入的内容
        
        //将图片转为data数据
        //指令为50%
        //值越小质量越差
        //体积越小
        let imageData=data.jpegData(compressionQuality: 0.5)
        
        conversation.sendImageMessage(imageData!)
    }
}

// MARK: - 聊天SDK消息回调
extension ChatController:JMessageDelegate {
    /// 发送消息的回调
    ///
    /// - Parameters:
    ///   - message: <#message description#>
    ///   - error: <#error description#>
    func onSendMessageResponse(_ message: JMSGMessage!, error: Error!) {
        if let error = error {
            //发送消息有错误
            //可以在这里处理界面
            print("ChatController onSendMessageResponse failed:\(error)")
        }else{
            //发送消息成功
            print("ChatController onSendMessageResponse success")
            
            //将消息添加到列表
            addMessage(message)
            
            //清除文本输入框
            clearTextView()
        }
    }
    
    //极光聊天在线消息回调
    func onReceive(_ message: JMSGMessage!, error: Error!) {
        let u1=message.fromUser
        
        //将接收到的消息标记为已读
        message.setMessageHaveRead { (data, error) in
            let u2=(data as! JMSGMessage).fromUser
            
            print("ChatController onReceive setMessageHaveRead:\(u1.username),\(u2.username)")
            
            if let error = error {
                //真实项目可以显示错误到界面
                print("ChatController onReceive setMessageHaveRead failed:\(error)")
            } else {
                print("ChatController onReceive setMessageHaveRead success")
                //添加到列表
                self.addMessage(message)
            }
        }
        
    }
}

// MARK: - 图片选择回调
extension ChatController:PhotoSolutionDelegate{
    /// 选择成功
    ///
    /// - Parameter images: <#images description#>
    func returnImages(_ images: [UIImage]) {
        print("ChatController select image count:\(images.count)")
        let data=images[0]
        
        sendImageMessage(data)
    }
    
    
    /// 取消选择
    func pickerCancel() {
        
    }
}
